package cn.com.sparkle.paxos.event;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;


public class EventsManager {

	private HashMap<Class<? extends Event>, EventDispatcher> eventDispatcherMap = new HashMap<Class<? extends Event>, EventDispatcher>();
	private LinkedList<Class<? extends Event>> eventDispatcherMapKeyList = new LinkedList<Class<? extends Event>>();

	public EventsManager() {
		registerEventDispatch(InstancePaxosEvent.class);
		registerEventDispatch(MasterChangePosEvent.class);
		registerEventDispatch(CatchUpEvent.class);
		registerEventDispatch(ExecutingInstanceChangeEvent.class);
		registerEventDispatch(ConfigureEvent.class);
		registerEventDispatch(NodeStateChangeEvent.class);
		registerEventDispatch(InstanceExecuteMaxPackageSizeEvent.class);
		registerEventDispatch(InstanceExecuteEvent.class);
		registerEventDispatch(SpeedControlEvent.class);
	}

	private void registerEventDispatch(Class<? extends Event> clazz) {
		eventDispatcherMap.put(clazz, new EventDispatcher());
		eventDispatcherMapKeyList.add(clazz);
	}

	private Class<? extends Event> getEventClass(Event event) {
		Iterator<Class<? extends Event>> iter = eventDispatcherMapKeyList
				.iterator();
		while (iter.hasNext()) {
			Class<? extends Event> clazz = iter.next();
			if (clazz.isInstance(event)) {
				return clazz;
			}
		}
		return null;
	}

	public void registerEvent(Event event) {
		EventDispatcher ed = eventDispatcherMap.get(getEventClass(event));
		if (ed != null) {
			ed.register(event);
		} else {
			throw new RuntimeException("unsupported event");
		}
	}

	public void unregisterEvent(Event event) {
		EventDispatcher ed = eventDispatcherMap.get(getEventClass(event));
		if (ed != null) {
			ed.unRegister(event);
		} else {
			throw new RuntimeException("unsupported event");
		}
	}

	public void doEvent(Class<? extends Event> clazz, Object... args) {
		EventDispatcher ed = eventDispatcherMap.get(clazz);
		if (ed != null) {
			ed.doAllEvent(args);
		} else {
			throw new RuntimeException("unsupported event");
		}
	}
}
